package com.example.gatewayserver.filter;

import com.example.gatewayserver.properties.NoAuthorizationProperties;
import com.example.gatewayserver.util.JwtUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.security.PublicKey;
import java.util.Collections;
import java.util.Map;

/**
 *
 * 实现的公共过滤器
 * 1.放过不需要授权验证的路径 如：/oauth/** 等springsecurity实现的oauth2接口
 * 2.通过获取jwt，通过oauth/token_key接口获取jwt的公钥和加密方式
 * 3.通过公钥验证jwt，如果验证通过，获取的jwt中的用户信息，保存到request的header中透传下去
 * @ClassName : AuthorizationFilter
 * @Description : 用于授权控制
 * @Author : tianshuo
 * @Date: 2021-08-13 21:57
 */
@Slf4j
//@EnableConfigurationProperties(NoAuthorizationProperties.class)
//@Component
public class AuthorizationFilter implements GlobalFilter, Ordered, InitializingBean {


    @Autowired
    private NoAuthorizationProperties noAuthorizationProperties;

    @Autowired
    private RestTemplate restTemplate;

    private PublicKey publicKey;

    @Configuration
    public class RibbonConfig {

        @Autowired
        private LoadBalancerClient loadBalancer;

        @Bean
        public RestTemplate restTemplate() {
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.setInterceptors(
                    Collections.singletonList(
                            new LoadBalancerInterceptor(loadBalancer)));

            return restTemplate;
        }
    }


    /**
     * 根据jwt获取到public key
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        this.publicKey = JwtUtils.genPulicKey(restTemplate);
    }

    /**
     * 解析jwt信息，包装信息到request作用域中传递下去
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        // 需要跳过，则直接继续走
        if (shouldSkipUrl(path)) {
            log.info("跳过{}",path);
            return chain.filter(exchange);
        }
        // jwt
        String authorization = request.getHeaders().getFirst("Authorization");
        log.info("jwt: {}",authorization);
        if (authorization == null) {
            //抛出异常
        }

        Claims claims = JwtUtils.validateJwtToken(authorization, publicKey);


        try {
            return chain.filter(wrapHeader(exchange,claims));
        } catch (JsonProcessingException e) {
            e.printStackTrace();

        }
        return null;
    }


    /**
     * 是否需要跳过url
     * 使用AntPathMatcher类匹配正则
     *
     * @param currentUrl
     * @return
     */
    private boolean shouldSkipUrl(String currentUrl) {
        //路径匹配器(简介SpringMvc拦截器的匹配器)
        //比如/oauth/** 可以匹配/oauth/token    /oauth/check_token等
        PathMatcher pathMatcher = new AntPathMatcher();
        for(String skipPath:noAuthorizationProperties.getNoAuthorizationSet()) {
            if(pathMatcher.match(skipPath,currentUrl)) {
                return true;
            }
        }
        return false;
    }

    private ServerWebExchange wrapHeader(ServerWebExchange serverWebExchange, Claims claims) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String loginUserInfo = mapper.writeValueAsString(claims);
//        String loginUserInfo = JSON.toJSONString(claims);

        //log.info("jwt的用户信息:{}",loginUserInfo);

        String memberId = claims.get("additionalInfo", Map.class).get("memberId").toString();

        String nickName = claims.get("additionalInfo",Map.class).get("nickName").toString();

        //向headers中放文件，记得build
        ServerHttpRequest request = serverWebExchange.getRequest().mutate()
                .header("username",claims.get("user_name",String.class))
                .header("memberId",memberId)
                .header("nickName",nickName)
                .build();

        //将现在的request 变成 change对象
        return serverWebExchange.mutate().request(request).build();
    }


    @Override
    public int getOrder() {
        return -1;
    }
}

